/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.thienloc.omap.controller.report;

import com.thienloc.omap.controller.BaseBean;
import com.thienloc.omap.entity.SyntaxDefinition;
import com.thienloc.omap.entity.report.BroadcastProductionOfSyntax;
import com.thienloc.omap.entity.report.BroadcastProductionOfUser;
import com.thienloc.omap.session.RequestQueueFacade;
import com.thienloc.omap.session.RequestQueueHistFacade;
import com.thienloc.omap.session.SyntaxDefinitionFacade;
import com.thienloc.omap.util.JsfUtil;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author GiangLT
 */
@ManagedBean
@ViewScoped
public class ProductionOfOperatorsBean extends BaseBean implements Serializable {

    @EJB
    private RequestQueueFacade requestQueueFacade;
    @EJB
    private RequestQueueHistFacade requestQueueHistFacade;
    @EJB
    private SyntaxDefinitionFacade syntaxDefinitionFacade;
    private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
    private Map<String, BroadcastProductionOfUser> userMap = new HashMap<String, BroadcastProductionOfUser>(0);
    private Date startTime;
    private Date endTime;
    private List<String> selectedDeliverProvider;
    private List<String> unparsableRequests = new ArrayList<String>();

    @PostConstruct
    public void init() {
        startTime = new Date();
        startTime.setHours(0);
        startTime.setMinutes(0);
        startTime.setSeconds(0);

        endTime = new Date();
        endTime.setHours(23);
        endTime.setMinutes(59);
        endTime.setSeconds(59);
    }

    public void reportOfToday() {
        startTime = new Date();
        startTime.setHours(0);
        startTime.setMinutes(0);
        startTime.setSeconds(0);

        endTime = new Date();
        endTime.setHours(23);
        endTime.setMinutes(59);
        endTime.setSeconds(59);

        report();
    }

    public void report() {
        try {
            unparsableRequests = new ArrayList<String>();
            //lấy danh sách người vận hành
            List<String> operatorUsers = syntaxDefinitionFacade.findAllUsername();
            userMap = new HashMap<String, BroadcastProductionOfUser>(operatorUsers.size());

            //tạo map default
            for (String username : operatorUsers) {
                BroadcastProductionOfUser broadcastProductionOfUser = new BroadcastProductionOfUser();
                broadcastProductionOfUser.setUsername(username);

                List<SyntaxDefinition> managingSyntaxes;
                try {
                    managingSyntaxes = syntaxDefinitionFacade.findByUsername(username);
                    for (SyntaxDefinition managingSyntax : managingSyntaxes) {
                        BroadcastProductionOfSyntax bpos = new BroadcastProductionOfSyntax(managingSyntax.getSyntax(), 0); //default = 0
                        bpos.setMdnSuffixEndRange(managingSyntax.getMdnSuffixEndRange());
                        bpos.setMdnSuffixStartRange(managingSyntax.getMdnSuffixStartRange());
                        broadcastProductionOfUser.addSyntax(bpos);
                    }
                    userMap.put(username, broadcastProductionOfUser);
                } catch (Exception ex) {
                    logger.error("", ex);
                    JsfUtil.addErrorMessage("Lỗi", ex.getMessage());
                }
            }

            logger.trace("[{}] Counting all received smses", getUsername());
            Map<String, Integer> requestDetailMap = requestQueueFacade.countProductionOfOperators(startTime, endTime, "6771", selectedDeliverProvider);
            Map<String, Integer> requestDetailHistMap = (requestQueueHistFacade.countProductionOfOperators(startTime, endTime, "6771", selectedDeliverProvider));
            for (String requestDetailHist : requestDetailHistMap.keySet()) {
                if (requestDetailMap.containsKey(requestDetailHist)) {
                    requestDetailMap.put(requestDetailHist, requestDetailHistMap.get(requestDetailHist) + requestDetailMap.get(requestDetailHist));
                } else {
                    requestDetailMap.put(requestDetailHist, requestDetailHistMap.get(requestDetailHist));
                }
            }
            logger.trace("[{}] Total {} broadcasted messages", getUsername(), requestDetailMap.size());

            Set<String> requestDetails = requestDetailMap.keySet();
            for (String requestDetail : requestDetails) {

                if (requestDetail != null && !requestDetail.trim().isEmpty()) {
                    //tách lấy cú pháp (từ đầu tiên)
                    String syntax;
                    if (requestDetail.startsWith("X2")) {
                        syntax = "X2";
                    } else {
                        syntax = requestDetail.split(" ")[0].trim();
                    }

                    List<SyntaxDefinition> syntaxDefinitions;
                    try {
                        syntaxDefinitions = syntaxDefinitionFacade.findBySyntax(syntax);
                        if (syntaxDefinitions.isEmpty()) {
                            //=> cú pháp ko tồn tại
                            logger.warn("Unparsable request detail: ({}) {}", requestDetailMap.get(requestDetail), requestDetail);
                            unparsableRequests.add("Production: " + requestDetailMap.get(requestDetail));
                            unparsableRequests.add("Sms: " + requestDetail);
                            unparsableRequests.add("----------------------------------------------------------------");
                            unparsableRequests.add("");
                        } else if (syntaxDefinitions.size() == 1
                                && syntaxDefinitions.get(0).getMdnSuffixEndRange() == -1
                                && syntaxDefinitions.get(0).getMdnSuffixStartRange() == -1) {
                            //=> cú pháp này chỉ có 1 người sử dụng
                            String username = syntaxDefinitions.get(0).getUsername();
                            BroadcastProductionOfUser broadcastProductionOfUser = userMap.get(username);
                            broadcastProductionOfUser.increaseProduction(syntax, requestDetailMap.get(requestDetail));
                            broadcastProductionOfUser.addMessageToSyntax(syntax, requestDetail);
                            broadcastProductionOfUser.setUniqueOperator(true);
                            //                        logger.debug("[{}]: Found {} {} - {}", new Object[]{getUsername(), username, requestDetail, requestDetailMap.get(requestDetail)});
                            //                        logger.debug("[{}]: {}", new Object[]{getUsername(), broadcastProductionOfUser.toString()});

                        } else {
                            //cú pháp có >2 người sử dụng
                            logger.debug("[{}]: 2 users syntax ({}): {}", new Object[]{getUsername(), requestDetailMap.get(requestDetail), requestDetail});
                            for (SyntaxDefinition syntaxDefinition : syntaxDefinitions) {
                                String username = syntaxDefinition.getUsername();
                                BroadcastProductionOfUser broadcastProductionOfUser = userMap.get(username);
                                broadcastProductionOfUser.addMessageToSyntax(syntaxDefinition.getSyntax(), requestDetail);
                            }
                        }
                    } catch (Exception ex) {
                        logger.error("", ex);
                    }
                }
            }

            Collection<BroadcastProductionOfUser> broadcastProductionOfUsers = userMap.values();
            for (BroadcastProductionOfUser broadcastProductionOfUser : broadcastProductionOfUsers) {
                if (!broadcastProductionOfUser.getUniqueOperator()) {
                    for (BroadcastProductionOfSyntax bpos : broadcastProductionOfUser.getProductionOfSyntax()) {
                        if (!bpos.getMessages().isEmpty()) {
                            Integer mdnSuffixStartRange = bpos.getMdnSuffixStartRange();
                            Integer mdnSuffixEndRange = bpos.getMdnSuffixEndRange();

                            if (logger.isDebugEnabled()) {
                                StringBuilder sb = new StringBuilder();
                                for (String requestDetail : bpos.getMessages()) {
                                    sb.append(requestDetail);
                                    sb.append(", ");
                                }
                                logger.debug("[{}] User: {}, Syntax: {}, Start: {}, End: {} , Rq Details: {}",
                                        new Object[]{
                                            getUsername(),
                                            broadcastProductionOfUser.getUsername(), bpos.getSyntax(),
                                            bpos.getMdnSuffixStartRange(), bpos.getMdnSuffixEndRange(),
                                            sb.toString()
                                        });
                            }

                            Integer count = requestQueueFacade.countProductionOfOperators("6771", bpos.getMessages(), selectedDeliverProvider, startTime, endTime, mdnSuffixStartRange, mdnSuffixEndRange);
                            count += requestQueueHistFacade.countProductionOfOperators("6771", bpos.getMessages(), selectedDeliverProvider, startTime, endTime, mdnSuffixStartRange, mdnSuffixEndRange);
                            bpos.setProduction(bpos.getProduction() + count);
                        }
                        logger.debug("[{}]: {}", new Object[]{getUsername(), broadcastProductionOfUser.toString()});
                    }
                }
            }
            try {
                exportToFile();
            } catch (IOException ex) {
                logger.error("", ex);
            }
        } catch (Exception ex) {
            logger.error("", ex);
        }
    }

    private void exportToFile() throws IOException {
        File file = new File(System.getProperty("user.home")
                + "/log/omap/user-production-from-"
                + (new SimpleDateFormat("yyyyMMddHHmmss")).format(startTime)
                + "-to-"
                + (new SimpleDateFormat("yyyyMMddHHmmss")).format(endTime));
        List<String> lines = new ArrayList<String>();
        for (BroadcastProductionOfUser bpou : getList()) {
            lines.add("********** Operator: " + bpou.getUsername()
                    + " | Total: " + bpou.getTotalProduction()
                    + " **********");
            lines.add("");
            for (BroadcastProductionOfSyntax bpos : bpou.getProductionOfSyntax()) {
                lines.add("====================================");
                lines.add("Syntax: " + bpos.getSyntax()
                        + " | From: " + bpos.getMdnSuffixStartRange() + " to: " + bpos.getMdnSuffixEndRange()
                        + " | Production: " + bpos.getProduction());
                for (String message : bpos.getMessages()) {
                    lines.add(message);
                    lines.add("------------------------------------");
                }

            }
        }

        FileUtils.writeLines(file, lines);
    }

    public List<BroadcastProductionOfUser> getList() {
        return new ArrayList<BroadcastProductionOfUser>(userMap.values());
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public List<String> getSelectedDeliverProvider() {
        return selectedDeliverProvider;
    }

    public void setSelectedDeliverProvider(List<String> selectedDeliverProvider) {
        this.selectedDeliverProvider = selectedDeliverProvider;
    }

    public List<String> getUnparsableRequests() {
        return unparsableRequests;
    }
}
